using System.Diagnostics;

namespace FluentParser.Expressions.Terminals.Parsing
{
    /// <summary>
    /// This expession succeeds only if the text can be found at the beginning
    /// of the cursor's position.
    /// </summary>
    /// <example><code>
    /// Symbol symbol = "SomeWord";
    /// 
    /// symbol.Parse("SomeWord")      --> "SomeWord"
    /// symbol.Parse("SomeOtherWord") --> failure
    /// </code></example>
    [DebuggerDisplay("[ParseExactExpressionTerminal Text={Text}]")]
    public class ParseExactExpressionTerminal : Expr<string>
    {
        public string Text { get; private set; }

        public ParseExactExpressionTerminal(string text)
        {
            Text = text;
            TypeOperation = OperationType.Parsing;
        }

        public override ParsingResult<string> Parse(GrammarContext context, int index)
        {
            int length = Text.Length;
            string text = context.Text;
            if (text.Length - index < length)
                return null;

            int current = index;
            for (int i = 0; i < length; i++)
            {
                if (text[current] != Text[i])
                    return null;
                current++;
            }

            return new ParsingResult<string>(index, length, Text);
        }

        public override void ParseNode(GrammarContext context, ParsingNodeResult node)
        {
            int symbolLength = Text.Length;
            int textIndex = node.Index;
            string text = context.Text;
            if (text.Length - textIndex < symbolLength)
            {
                node.ExploredLength = textIndex - node.Index + 1;
            }
            else
            {
                for (int i = 0; i < symbolLength; i++)
                {
                    if (text[textIndex] != Text[i])
                    {
                        node.ExploredLength = i + 1;
                        return;
                    }
                    textIndex++;
                }

                node.ExploredLength = Text.Length;
                node.Length = Text.Length;
                node.IsSuccess = true;
                node.Value = Text;
            }
        }
    }
}